package vip.xiaomaoxiaoke.idempotent.support;


import com.google.common.collect.Maps;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import vip.xiaomaoxiaoke.idempotent.IdempotentExecutor;
import vip.xiaomaoxiaoke.idempotent.IdempotentMeta;
import vip.xiaomaoxiaoke.idempotent.IdempotentMetaParser;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * 幂等方法拦截
 */
public class IdempotentInterceptor
    implements MethodInterceptor {

    /**
     * 元数据缓存
     * */
    private final Map<Method, IdempotentExecutor> cache = Maps.newHashMap();

    /**
     * 元数据解析器
     * */
    private final IdempotentMetaParser parser;

    /**
     * 执行器工厂集合
     * */
    private final IdempotentExecutorFactories factories;

    public IdempotentInterceptor(IdempotentMetaParser parser,
                                 IdempotentExecutorFactories factories) {
        this.parser = parser;
        this.factories = factories;
    }

    /**
     * 拦截方法
     * */
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        IdempotentExecutor executor = this.cache.computeIfAbsent(invocation.getMethod(), this::createExecutor);


        if (executor != null){
            return executor.invoke(invocation);
        }
        return invocation.proceed();
    }

    /**
     * 解析元数据并创建执行器
     * */
    private IdempotentExecutor createExecutor(Method method) {
        IdempotentMeta meta = this.parser.parse(method);
        return factories.create(meta);
    }
}
